package com.caiden_micheal.user.web;

import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.caiden_micheal.base.aop.annotation.PermissionVerify;
import com.caiden_micheal.base.constant.LoggerHead;
import com.caiden_micheal.base.domain.AjxResult;
import com.caiden_micheal.base.properties.AESProperties;
import com.caiden_micheal.base.properties.URLProperties;
import com.caiden_micheal.base.utils.AESUtil;
import com.caiden_micheal.base.utils.EncodeURIComponent;
import com.caiden_micheal.base.utils.JwtUtil;
//import com.caiden_micheal.user.utils.PermissionCheckUtil;
import com.caiden_micheal.menu.domain.Menu;
import com.caiden_micheal.menu.service.MenuService;
import com.caiden_micheal.user.domain.User;
import com.caiden_micheal.user.service.EmailSendService;
import com.caiden_micheal.user.service.UserService;
import com.caiden_micheal.user.vo.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;

@RestController
@RequestMapping("/user")
public class UserLoginController {
    private static final Logger logger = LoggerFactory.getLogger(UserLoginController.class);
    @Autowired
    private EmailSendService emailSendService;
    @Autowired
    private UserService userService;
    @Autowired
    private AESProperties aesProperties;
    @Autowired
    private URLProperties urlProperties;
    @Autowired
    private MenuService menuService;

    @PostMapping("/login")
    public AjxResult sysLogin(@RequestBody String data) {
        if (StringUtils.isEmpty(data)) {
            logger.warn(LoggerHead.warnHead() + "Request parameter is empty");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        data = EncodeURIComponent.decode(data, "UTF-8");
        data = data.substring(0, data.length() - 1);
        String decrypt = AESUtil.decrypt(data, aesProperties.getSecretKey());
        ObjectMapper objectMapper = new ObjectMapper();
        LoginVO loginVO;
        try {
            loginVO = objectMapper.readValue(decrypt, LoginVO.class);
        } catch (JsonProcessingException e) {
            logger.error(LoggerHead.errorHead() + "JSON format conversion exception, " + e.getMessage());
            return AjxResult.paramError("参数传递错误");
        }
        if (loginVO == null) {
            logger.warn(LoggerHead.warnHead() + "loginVO is Null");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        Long time = loginVO.getTime();
        if ((System.currentTimeMillis() - time) / 1000 > 2) {
            logger.warn(LoggerHead.warnHead() + "Request timed out or tampered with: " + decrypt);
            return AjxResult.requestTimeOut("请求超时或加密信息被篡改，已记录该次请求行为");
        }
        if (StringUtils.isEmpty(loginVO.getUsername()) || StringUtils.isEmpty(loginVO.getPassword())) {
            logger.warn(LoggerHead.warnHead() + "userName or password is empty: " + decrypt);
            return AjxResult.paramError("用户名和密码禁止为空");
        }
        User user = userService.findByUserName(loginVO.getUsername());
        if (user == null) {
            logger.warn(LoggerHead.warnHead() + "User not found: " + decrypt);
            return AjxResult.userNotFound("未找到用户：" + loginVO.getUsername());
        } else if (user.getDisabled() == 2) {
            logger.warn(LoggerHead.warnHead() + "User not activated: " + decrypt);
            return AjxResult.userIsAbnormal("请查收邮件，并点击连接激活用户后继续登录");
        } else if (!Objects.equals(loginVO.getPassword(), AESUtil.decrypt(user.getPassword(), aesProperties.getSecretKey()))) {
            logger.warn(LoggerHead.warnHead() + "wrong password: " + decrypt);
            return AjxResult.passwordError(loginVO.getUsername() + " 的密码错误");
        }
        List<String> authorityNameList = userService.findUserAuthorityNameListByUserId(user.getId(), true);
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getId());
        claims.put("username", loginVO.getUsername());
        String randomFlag = UUID.randomUUID().toString();
        claims.put("flag", randomFlag);
        userService.userOnlineStatusSet(user.getId(), randomFlag);
        String token = JwtUtil.createToken(claims);
        HashMap<String, Object> restMap = new HashMap<>();
        restMap.put("token", token);
        restMap.put("authority", authorityNameList);
        List<Menu> menuInfo = menuService.findEnableMenu(authorityNameList, false);
        restMap.put("menuInfo", JSON.toJSONString(menuInfo));
        return AjxResult.success(restMap);
    }

    @PostMapping("/register")
    public AjxResult sysRegister(@RequestBody String data) {
        if (StringUtils.isEmpty(data)) {
            logger.warn(LoggerHead.warnHead() + "Request parameter is empty");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        data = EncodeURIComponent.decode(data, "UTF-8");
        data = data.substring(0, data.length() - 1);
        String decrypt = AESUtil.decrypt(data, aesProperties.getSecretKey());
        ObjectMapper objectMapper = new ObjectMapper();
        RegisterVO registerVO;
        try {
            registerVO = objectMapper.readValue(decrypt, RegisterVO.class);
        } catch (JsonProcessingException e) {
            logger.error(LoggerHead.errorHead() + "JSON format conversion exception, " + e.getMessage());
            throw new RuntimeException(e);
        }
        if (registerVO == null) {
            logger.warn(LoggerHead.warnHead() + "registerVO is Null");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        Long time = registerVO.getTime();
        if ((System.currentTimeMillis() - time) / 1000 > 2) {
            logger.warn(LoggerHead.warnHead() + "Request timed out or tampered with: " + decrypt);
            return AjxResult.requestTimeOut("请求超时或加密信息被篡改，已记录该次请求行为");
        }
        Integer flag = userService.validEmailAndUserNameRepeat(registerVO.getUsername(), registerVO.getEmail());
        if (flag == 1) {
            logger.warn(LoggerHead.warnHead() + "UserName has already been registered: " + registerVO.getUsername());
            return AjxResult.userNameRepeat("该用户名已被注册，请更换用户名");
        } else if (flag == 2) {
            logger.warn(LoggerHead.warnHead() + "The mailbox has been registered: " + registerVO.getEmail());
            return AjxResult.emailRepeat("该邮箱已注册过用户，请更换邮箱或选择注销原用户");
        }
        registerVO.setPassword(AESUtil.encrypt(registerVO.getPassword(), aesProperties.getSecretKey()));
        userService.registerUser(registerVO);
        Boolean emailSendFlag = emailSendService.sendRegisterEmail(null, registerVO);
        if (!emailSendFlag) {
            userService.delUserById(registerVO.getId());
            logger.warn(LoggerHead.warnHead() + "User registration failed: " + decrypt);
            return AjxResult.emailSendError("用户注册失败，请稍后重试或联系管理员查看后台日志");
        }
        return AjxResult.success("注册成功");
    }

    @GetMapping("/activate")
    public AjxResult sysUserActivate(@RequestParam("data") String data) {
        String decrypt = AESUtil.decrypt(data, aesProperties.getSecretKey());
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, String> content;
        try {
            content = objectMapper.readValue(decrypt, Map.class);
        } catch (JsonProcessingException e) {
            logger.error(LoggerHead.errorHead() + "JSON format conversion exception, " + e.getMessage());
            return AjxResult.paramError("JSON格式转换异常：" + e.getMessage());
        }
        Long time = Long.parseLong(content.get("time"));
        Long id = Long.valueOf(content.get("userId"));
        if ((System.currentTimeMillis() - time) / 1000 > 300) {
            User user = userService.findByUserId(id);
            if (user == null) {
                return AjxResult.requestTimeOut("用户不存在，请重新注册：" + urlProperties.getFrontBaseUrl() + "/register");
            } else if (user.getDisabled() != 0) {
                userService.delUserById(id);
                return AjxResult.requestTimeOut("邮件已过有效期，用户信息已清空，请重新注册：" + urlProperties.getFrontBaseUrl() + "/register");
            } else {
                return AjxResult.paramError("用户已被激活");
            }
        }
        userService.activeUsreById(id);
        return AjxResult.success("用户激活成功，请返回登陆界面登录：" + urlProperties.getFrontBaseUrl() + "/login");
    }

    @PostMapping("/sendEmailCode")
    public AjxResult sendEmailCode(@RequestBody String data) {
        if (StringUtils.isEmpty(data)) {
            logger.warn(LoggerHead.warnHead() + "Request parameter is empty");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        data = EncodeURIComponent.decode(data, "UTF-8");
        data = data.substring(0, data.length() - 1);
        String decrypt = AESUtil.decrypt(data, aesProperties.getSecretKey());
        ObjectMapper objectMapper = new ObjectMapper();
        EmailCodeVO emailCodeVO;
        try {
            emailCodeVO = objectMapper.readValue(decrypt, EmailCodeVO.class);
        } catch (JsonProcessingException e) {
            logger.error(LoggerHead.errorHead() + "JSON format conversion exception, " + e.getMessage());
            return AjxResult.paramError("参数传递错误");
        }
        if (emailCodeVO == null) {
            logger.warn(LoggerHead.warnHead() + "emailCodeVO is Null");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        Long time = emailCodeVO.getTime();
        if ((System.currentTimeMillis() - time) / 1000 > 2) {
            logger.warn(LoggerHead.warnHead() + "Request timed out or tampered with: " + decrypt);
            return AjxResult.requestTimeOut("请求超时或加密信息被篡改，已记录该次请求行为");
        }
        // 查询用户信息，发送邮件
        User user = userService.findByUserName(emailCodeVO.getUsername());
        Boolean emailSendFlag = emailSendService.sendRegisterEmail(user, null);
        if (!emailSendFlag) {
            logger.warn(LoggerHead.warnHead() + "SendEmailCode failed: " + decrypt);
            return AjxResult.emailSendError("邮件失败，请稍后重试或联系管理员查看后台日志");
        }
        return AjxResult.success("成功");
    }

    @PostMapping("/modifyPassword")
    public AjxResult modifyPassword(@RequestBody String data) {
        // TODO 密码修改
        /*if (StringUtils.isEmpty(data)) {
            logger.warn(LoggerHead.warnHead() + "Request parameter is empty");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        data = EncodeURIComponent.decode(data, "UTF-8");
        data = data.substring(0, data.length() - 1);
        String decrypt = AESUtil.decrypt(data, aesProperties.getSecretKey());
        ObjectMapper objectMapper = new ObjectMapper();
        ForgetPwdVO forgetPwdVO;
        try {
            forgetPwdVO = objectMapper.readValue(decrypt, ForgetPwdVO.class);
        } catch (JsonProcessingException e) {
            logger.error(LoggerHead.errorHead() + "JSON format conversion exception, " + e.getMessage());
            return AjxResult.paramError("参数传递错误");
        }
        if (forgetPwdVO == null) {
            logger.warn(LoggerHead.warnHead() + "forgetPwdVO is Null");
            return AjxResult.paramError("参数提交有误，请确认后重试");
        }
        Long time = forgetPwdVO.getTime();
        if ((System.currentTimeMillis() - time) / 1000 > 2) {
            logger.warn(LoggerHead.warnHead() + "Request timed out or tampered with: " + decrypt);
            return AjxResult.requestTimeOut("请求超时或加密信息被篡改，已记录该次请求行为");
        }*/
        return null;
    }

    @PermissionVerify(permissionArray = {"mer:p", "user:index", "mer:p"})
    @PostMapping("/test")
    public AjxResult test() {
        /*if (!PermissionCheckUtil.checkPermission("mer:p")) {
            return AjxResult.unknownError("无权访问");
        }*/
        return AjxResult.success("TEST页面");
    }
}
